package com.gofun.framework.redis;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

public class RedisServiceImpl implements RedisService {

	Logger logger = LoggerFactory.getLogger(RedisServiceImpl.class);

	private static final Integer DEFAULT_exceed_SECONDS = 30 * 24 * 60 * 60;
	
	//private static final Integer USER_TIME_OUT = 60 * 60 * 1000;
	@Autowired
	private RedisTemplate<String, Object> redisTemplate;

	/**
	 * 默认30天过期
	 * 
	 * @param key
	 * @param object
	 */
	@Override
	public void set(String key, Object object) {
		set(key, object, DEFAULT_exceed_SECONDS);
	}

	@Override
	public void set(String key, Object object, long timeout) {
		if (key == null) {
			return;
		}
		try {
			redisTemplate.opsForValue().set(key, object, timeout,
					TimeUnit.SECONDS);
		} catch (Exception e) {
			logger.error(String.format(
					"redis set operation for value failed by key [%s]: %s",
					key, e.getMessage()));
			return;
		}
	}

	@Override
	public Object get(String key) {
		if (key == null) {
			return null;
		}
		Object object = null;

		try {
			object = redisTemplate.opsForValue().get(key);
		} catch (Exception e) {
			logger.error(String.format(
					"redis get operation for value failed by key [%s]: %s",
					key, e.getMessage()));
			return object;
		}

		return object;
	}

	@Override
	public int boundValueOps(String key) {
		if (key == null) {
			return 0;
		}
		String object = null;

		try {
			object = redisTemplate.boundValueOps(key).get(0, -1);
			if (StringUtils.trimToNull(object) == null) {
				return 0;
			}
		} catch (Exception e) {
			logger.error(String.format(
					"redis get operation for value failed by key [%s]: %s",
					key, e.getMessage()));
			return 0;
		}

		return Integer.parseInt(object);
	}

	@Override
	public Object getAndSet(String key, Object value, long timeout) {
		Object object = redisTemplate.opsForValue().getAndSet(key, value);
		redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
		return object;
	}

	@Override
	public void delete(String key) {
		try {
			redisTemplate.delete(key);
		} catch (Exception e) {
			logger.error(String.format(
					"redis get operation for value failed by key [%s]: %s",
					key, e.getMessage()));
		}

	}

	/**
	 * bitmap
	 * 
	 * @param key
	 * @param offset
	 *            例： 手机号
	 * @param value
	 *            true false
	 * @return
	 */
	@Override
	public boolean setBit(String key, long offset, boolean value) {
		return redisTemplate.opsForValue().setBit(key, offset, value);
	}

	/**
	 * bitmap
	 * 
	 * @param key
	 * @param offset
	 * @return
	 */
	@Override
	public boolean getBit(String key, long offset) {
		return redisTemplate.opsForValue().getBit(key, offset);
	}

	/**
	 * 
	 * @param key
	 * @param delta
	 * @return
	 */
	@Override
	public int increment(String key, long delta, long timeout) {
		Long increment = redisTemplate.opsForValue().increment(key, delta);
		redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
		return increment.intValue();
	}

	/**
	 * 存储redis队列 顺序存储
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public Long leftPush(String key, String value) {
		return redisTemplate.opsForList().leftPush(key, value);
	}
	
	public Long rightPush(String key, String value) {
		return redisTemplate.opsForList().rightPush(key, value);
	}
	/**
	 * 将列表 source 中的最后一个元素(尾元素)弹出，并返回给客户端
	 * 
	 * //@param key
	 * @return
	 */
	public String rightPopAndLeftPush(String sourceKey, String destinationKey) {
		return (String) redisTemplate.opsForList().rightPopAndLeftPush(
				sourceKey, destinationKey);
	}

	/**
	 * 移除队列
	 * 
	 * @param key
	 * @return
	 */
	public String rightPop(String key) {
		return (String) redisTemplate.opsForList().rightPop(key);
	}

	/**
	 * 栈/队列长
	 * 
	 * @param key
	 * @return
	 */
	public Long length(String key) {
		return redisTemplate.opsForList().size(key);
	}

	/**
	 * 指定key 失效剩余时间
	 */
	public Long ttl(String key){
		return redisTemplate.getExpire(key);
	}

	/**
	 * hash 自增
	 */
	public Long increment(String name, String key, Long offset){
		//正常的序列化反序列化需要在配置文件里面指定，但是考虑到已经有用户进行使用，故在此配置
		StringRedisSerializer serializer = new StringRedisSerializer();
		redisTemplate.setHashKeySerializer(serializer);
		redisTemplate.setHashValueSerializer(serializer);
		return redisTemplate.boundHashOps(name).increment(key, offset);
	}

	/**
	 * 指定keyName 失效时间
	 */
	public Boolean expire(String keyName, Long time, TimeUnit unit){
		StringRedisSerializer serializer = new StringRedisSerializer();
		redisTemplate.setHashKeySerializer(serializer);
		redisTemplate.setHashValueSerializer(serializer);
		return redisTemplate.expire(keyName, time, unit);
	}
	public Map<Object,Object> getAllHashVal(String namespace){
		StringRedisSerializer serializer = new StringRedisSerializer();
		redisTemplate.setHashKeySerializer(serializer);
		redisTemplate.setHashValueSerializer(serializer);
		BoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps(namespace);
		Set<Object> keys = operations.keys();
		HashMap<Object, Object> hashMap = new HashMap<Object, Object>();
		for (Object key : keys) {
			hashMap.put(key,operations.get(key));
		}
		return hashMap;
	}

	/**
	 * 保存redis
	 */
	public void addHash(String loginRedisName, String userID, String json , Integer USER_TIME_OUT) {
		redisTemplate.opsForHash().put(loginRedisName, userID, json);
		redisTemplate.expire(userID,USER_TIME_OUT, TimeUnit.SECONDS);
	}
	

}
